# 数据预处理：PDF转WORD和MD文件

from pdf2docx import Converter  # PDF转DOCX转换器 是从第三方库导入
import re                       # 正则表达式模块
import os                       # 操作系统路径模块
import csv                      # CSV文件操作模块
from docx import Document       # DOCX文档操作模块

# 定义非空白语义分隔符元组
_NON_WHITESPACE_SEMANTIC_SPLITTERS = (
    '。\n\n', '。\n', '。', '？', '！'
                              '；', '\n', '\r'  '）', '”', '’', '】', '……',  # Sentence terminators.
    '?', '!', '*',  # Sentence terminators.
    ';', '，', '(', ')', '[', ']', "“", "”", '‘', '’', "'", '"', '`',  # Clause separators.
    ':', '—', '...',  # Sentence interrupters.
    '/', '\\', '–', '&', '-',  # Word joiners.
)


def split_text(text, chunk_size=400):
    """按语义标点符号分割长文本为指定大小的块
    参数：
        text - 输入文本
        chunk_size - 目标块大小（默认400字符）
    返回：分割后的文本块列表
    """
    # 按分隔符优先级逐级尝试切分
    for splitter in _NON_WHITESPACE_SEMANTIC_SPLITTERS:
        if splitter:  # 过滤空字符串（尽管当前元组中无空值）
            # 用当前分隔符分割文本
            parts = text.split(splitter)
            chunks = []
            current_chunk = ''

            # 重组分割后的段落
            for part in parts:
                # 检查当前块长度是否超限
                if len(current_chunk) + len(part) + len(splitter) <= chunk_size:
                    current_chunk += part + splitter  # 拼接段落
                else:
                    if current_chunk:
                        chunks.append(current_chunk.strip())  # 保存当前块
                    current_chunk = part + splitter  # 开始新块
            if current_chunk:  # 添加最后一块
                chunks.append(current_chunk.strip())

            # 验证所有块是否符合大小要求
            if all(len(chunk) <= chunk_size for chunk in chunks):
                return chunks

    # 所有分隔符无效时，按固定长度切分
    return [text[i:i + chunk_size] for i in range(0, len(text), chunk_size)]


def pdf_to_docx(pdf_file_path):
    """将PDF文件转换为DOCX格式
    参数：
        pdf_file_path - PDF文件路径
    返回：生成的DOCX文件路径（失败返回False）
    """
    try:
        # 构造输出路径：同目录下，后缀改为.docx
        docx_path = os.path.join(
            os.path.dirname(pdf_file_path),
            os.path.basename(pdf_file_path).split(".")[0] + ".docx"
        )
        # 执行转换操作
        cv = Converter(pdf_file_path)
        cv.convert(docx_path)
        cv.close()
        return docx_path
    except Exception as e:
        print(f"转换过程中发生错误：{str(e)}")
        return False


def pdf_to_md_and_csv(pdf_file_path, max_length=400):
    """主处理函数：PDF转MD和CSV
    参数：
        pdf_file_path - 输入PDF路径
        max_length - 文本块最大长度（默认400）
    返回：生成三个文件（DOCX/MD/CSV）
    """
    # Step 1. 转换PDF到DOCX
    docx_path = pdf_to_docx(pdf_file_path)
    if not docx_path:
        return False

    # Step 2. 读取DOCX内容
    docx = Document(docx_path)
    result = []
    current_text = ""

    # Step 3. 处理每个段落
    for paragraph in docx.paragraphs:
        # 文本预处理
        sections = paragraph.text.strip()  # 去除首尾空白
        sections = re.sub(r'\s+', ' ', sections)  # 合并连续空白
        sections = re.sub(r'(.)\1{4,}', r'\1', sections)  # 替换重复4+次的字符

        # 处理超长段落分块
        if len(sections) > max_length:
            # 动态计算分块大小
            chunk_size = int(len(sections) / ((len(sections) // max_length) + 1))
            sections = split_text(sections, chunk_size=chunk_size)

        # 统一转换为列表处理
        if isinstance(sections, str):
            sections = [sections]

        # 分块处理逻辑
        for section in sections:
            # 检查当前块长度
            if not current_text or len(current_text) + len(section) + 1 <= max_length:
                current_text += " " + section  # 拼接文本
            else:
                # 查找最后句号进行语义分割
                period_index = current_text.rfind('。')
                if period_index != -1:
                    # 分割到句号处
                    period_text = current_text[:period_index + 1].strip()
                    result.append(period_text)
                    current_text = current_text[period_index + 1:].strip() + section
                else:
                    # 无句号则直接分割
                    result.append(current_text.strip())
                    current_text = section

    # 添加最后剩余文本
    if current_text.strip():
        result.append(current_text.strip())

    # Step 4. 生成CSV文件
    base_name = os.path.basename(pdf_file_path).split(".")[0]
    output_dir = os.path.dirname(pdf_file_path)

    csv_output_path = os.path.join(output_dir, f"{base_name}_pdf2docx.csv")
    with open(csv_output_path, 'w', newline='', encoding='utf-8') as csvfile:
        csvwriter = csv.writer(csvfile)
        csvwriter.writerow(['filename', 'text'])  # 写入列头
        csvwriter.writerows([[os.path.basename(pdf_file_path), chunk] for chunk in result])  # 写入数据行

    # Step 5. 生成MD文件
    md_output_path = os.path.join(output_dir, f"{base_name}_pdf2docx.md")
    with open(md_output_path, 'w', encoding='utf-8') as md_file:
        md_file.write('\n\n'.join(result))  # 用双换行分隔段落

    # 打印处理结果
    print(f"处理完成: {pdf_file_path}")
    print(f"生成文档: {docx_path}")
    print(f"生成CSV文件: {csv_output_path}")
    print(f"生成MD文件: {md_output_path}")


if __name__ == "__main__":
    pdf_file_path = r"D:/desktop.u.mine/大模型/结果2/中荷传世赢家（臻享版）终身寿险产品说明.pdf"
    pdf_to_md_and_csv(pdf_file_path)




